/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package bpmlab.kivulifx.controller;

import bpmlab.kivulifx.Main;
import bpmlab.kivulifx.application.Context;
import bpmlab.kivulifx.component.*;
import bpmlab.kivulifx.entity.*;
import bpmlab.kivulifx.persistence.Persistence;
import bpmlab.kivulifx.persistence.PersistenceFactory;
import bpmlab.kivulifx.util.DialogsCustom;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.FileChooser;

/**
 * FXML Controller class
 *
 * @author bpmlab
 */
public class IndexController implements Initializable {

    @FXML
    private BorderPane masterPane;
    @FXML
    private ScrollPane paneCentral;
    @FXML
    private GridPane propertiesPane;
    @FXML
    private MenuItem newProject;
    @FXML
    private MenuItem openProject;
    @FXML
    private MenuItem save;
    @FXML
    private MenuItem saveAt;
    @FXML
    private MenuItem closeCurrentProject;
    @FXML
    private MenuItem createCircle;
    @FXML
    private MenuItem createRectangle;
    @FXML
    private TextField radius;
    @FXML
    private TextField rotate;
    @FXML
    private TextField width;
    @FXML
    private TextField height;

    private Context context = Context.getCurrentInstance();
    private Environment environment;
    private SimpleObjectProperty<Node> nodeSelected = new SimpleObjectProperty<>();

    /**
     * Initializes the controller class.
     *
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        BooleanBinding nullProject = context.currentProjectProperty().isNull();
        propertiesPane.visibleProperty().bind(nodeSelected.isNotNull().and(nullProject.not()));
        save.disableProperty().bind(nullProject);
        saveAt.disableProperty().bind(nullProject);
        closeCurrentProject.disableProperty().bind(nullProject);
        createCircle.disableProperty().bind(nullProject);
        createRectangle.disableProperty().bind(nullProject);

        radius.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            if (nodeSelected.get() instanceof Circle && !newValue) {
                Circle rec = (Circle) nodeSelected.get();
                try {
                    rec.setRadius(Double.parseDouble(radius.getText()));
                } catch (Exception e) {
                    radius.setText(rec.getRadius() + "");
                }
            }
        });

        width.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            Rectangle rec = null;
            if (nodeSelected.get() instanceof Rectangle && nodeSelected.get() != null) {
                rec = (Rectangle) nodeSelected.get();
            } else {
                return;
            }

            if (newValue) {
                width.setText(rec.getWidth() + "");
            } else {
                try {
                    rec.setWidth(Double.parseDouble(width.getText()));
                } catch (Exception e) {
                    width.setText(rec.getWidth() + "");
                }
            }
        });

        height.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            if (nodeSelected.get() instanceof Rectangle && !newValue) {
                Rectangle rec = (Rectangle) nodeSelected.get();
                try {
                    rec.setHeight(Double.parseDouble(height.getText()));
                } catch (Exception e) {
                    height.setText(rec.getHeight() + "");
                }
            }
        });

        rotate.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
            if (!newValue) {
                try {
                    nodeSelected.get().setRotate(Double.parseDouble(rotate.getText()));
                } catch (Exception e) {
                    rotate.setText(nodeSelected.get().getRotate() + "");
                }
            }
        });
    }

    public void saveAction() throws Exception {
        Persistence persistence = PersistenceFactory.createPersistence();
        persistence.save(context.currentProject());
    }

    public void saveAtAction() {
    }

    public void newProjectAction() throws IOException {
        boolean ok = DialogsCustom.newProject();
        if (ok) {
            environment = new Environment(paneCentral.getWidth(), paneCentral.getHeight());
            paneCentral.setContent(environment);
        }
    }

    public void createCircleAction() {
        KVCircle circle = new KVCircle();
        circle.setOnMouseClicked((MouseEvent event) -> {
            nodeSelected.set(circle);
            radius.setDisable(false);
            width.setDisable(true);
            height.setDisable(true);
        });
        environment.addShape(circle);
        context.addShapeToCurrentProject(circle.getModel());
    }

    public void createRectangleAction() {
        KVRectangle rectangle = new KVRectangle();
        rectangle.setOnMouseClicked((MouseEvent event) -> {
            nodeSelected.set(rectangle);
            radius.setDisable(true);
            width.setDisable(false);
            height.setDisable(false);
        });
        environment.addShape(rectangle);
        context.addShapeToCurrentProject(rectangle.getModel());
    }

    public void openProjectAction() {
        FileChooser fileChooser = new FileChooser();
        File file = fileChooser.showOpenDialog(Main.stage);
        Persistence persistence = PersistenceFactory.createPersistence();
        Project project = null;

        try {
            project = persistence.open(file);
        } catch (Exception ex) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setHeaderText("Error loading file");
            alert.setContentText("Could not load file");
            alert.show();
        }
        context.setCurrentProject(project);

        environment = new Environment(paneCentral.getWidth(), paneCentral.getHeight());
        paneCentral.setContent(environment);
        for (ShapeModel shape : project.getShapes()) {
            if (shape instanceof CircleModel) {
                CircleModel model = (CircleModel) shape;
                KVCircle circle = new KVCircle(model);
                circle.setOnMouseClicked((MouseEvent event) -> {
                    nodeSelected.set(circle);
                    radius.setDisable(false);
                    width.setDisable(true);
                    height.setDisable(true);
                });
                environment.addShape(circle);
            } else if (shape instanceof RectangleModel) {
                RectangleModel model = (RectangleModel) shape;
                KVRectangle rectangle = new KVRectangle(model);
                rectangle.setOnMouseClicked((MouseEvent event) -> {
                    nodeSelected.set(rectangle);
                    radius.setDisable(true);
                    width.setDisable(false);
                    height.setDisable(false);
                });
                environment.addShape(rectangle);
            }
        }
    }

    public void closeCurrentProjectAction() {
        context.setCurrentProject(null);
        paneCentral.setContent(null);
    }

    public void exitAction() {
        System.exit(0);
    }

}
